package com.xxl.job.executor.util;

import com.xxl.job.executor.enums.StatusCodeEnum;
import com.xxl.job.executor.exception.BusinessException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

/**
 * GZIP工具
 *
 * @author <a href="mailto:zlex.dongliang@gmail.com">梁栋</a>
 * @since 1.0
 */
public abstract class GZipUtils {
	private static Logger logger = LoggerFactory.getLogger(GZipUtils.class);
	public static final int BUFFER = 1024;
	public static final String EXT = ".zip";

	/**
	 * 数据压缩
	 *
	 * @param data
	 * @return
	 * @throws Exception
	 */
	public static byte[] compress(byte[] data) throws Exception {
		ByteArrayInputStream bais = null;
		ByteArrayOutputStream baos = null;
		if (data == null) {
			return null;
		}
		try {
			bais = new ByteArrayInputStream(data);
			baos = new ByteArrayOutputStream();
			// 压缩
			compress(bais, baos);
			byte[] output = baos.toByteArray();
			baos.flush();
			return output;
		} finally {
			if (baos != null)
				baos.close();
			if (bais != null)
				bais.close();
		}

	}

	/**
	 * 文件压缩
	 *
	 * @param file
	 * @param delete
	 *            是否删除原始文件
	 * @throws Exception
	 */
	public static void compress(File file, boolean delete) throws Exception {
		FileInputStream fis = null;
		FileOutputStream fos = null;
		try {
			fis = new FileInputStream(file);
			fos = new FileOutputStream(file.getPath() + EXT);
			compress(fis, fos);
			fos.flush();
			if (delete) {
				file.delete();
			}
		} catch (Exception e) {
			logger.error("error", e);
			throw new BusinessException(StatusCodeEnum.FILE_OPR_ERR, "GZIP压缩异常" + file.getName());
		} finally {
			if (fos != null)
				fos.close();
			if (fis != null)
				fis.close();
		}

	}

	/**
	 * 数据压缩
	 *
	 * @param is
	 * @param os
	 * @throws Exception
	 */
	public static void compress(InputStream is, OutputStream os) throws Exception {
		GZIPOutputStream gos = null;
		try {
			gos = new GZIPOutputStream(os);
			int count;
			byte data[] = new byte[BUFFER];
			while ((count = is.read(data, 0, BUFFER)) != -1) {
				gos.write(data, 0, count);
			}
			gos.finish();
			gos.flush();
		} finally {
			if (gos != null)
				gos.close();
		}
	}

	/**
	 * gzip文件压缩
	 *
	 * @param path
	 * @param delete
	 *            是否删除原始文件
	 * @throws Exception
	 */
	public static void compress(String path, boolean delete) throws Exception {
		File file = new File(path);
		compress(file, delete);
	}

	/**
	 * 数据解压缩
	 *
	 * @param data
	 * @return
	 * @throws Exception
	 */
	public static byte[] decompress(byte[] data) throws Exception {
		ByteArrayInputStream bais = null;
		ByteArrayOutputStream baos = null;
		try {
			bais = new ByteArrayInputStream(data);
			baos = new ByteArrayOutputStream();
			decompress(bais, baos);
			data = baos.toByteArray();
			baos.flush();
			return data;
		} finally {
			if (baos != null)
				baos.close();
			if (bais != null)
				bais.close();
		}
	}

	/**
	 * 文件解压缩
	 *
	 * @param file
	 * @param delete
	 *            是否删除原始文件
	 * @throws Exception
	 */
	public static void decompress(File file, boolean delete) throws Exception {
		FileInputStream fis = null;
		FileOutputStream fos = null;
		try {
			fis = new FileInputStream(file);
			fos = new FileOutputStream(file.getPath().replace(EXT, ""));
			decompress(fis, fos);
			fos.flush();
			if (delete) {
				file.delete();
			}
		} catch (Exception e) {
			logger.error("error", e);
			throw new BusinessException(StatusCodeEnum.FILE_OPR_ERR, "GZIP decompress ERR:" + file.getName());
		} finally {
			if (fis != null)
				fis.close();
			if (fos != null)
				fos.close();
		}
	}

	/**
	 * 数据解压缩
	 *
	 * @param is
	 * @param os
	 * @throws Exception
	 */
	public static void decompress(InputStream is, OutputStream os) throws Exception {
		GZIPInputStream gis = null;
		try {
			gis = new GZIPInputStream(is);
			int count;
			byte data[] = new byte[BUFFER];
			while ((count = gis.read(data, 0, BUFFER)) != -1) {
				os.write(data, 0, count);
			}
		} finally {
			if (gis != null)
				gis.close();

		}
	}

	/**
	 * 解压.gz文件
	 * 
	 * @param file
	 *            上传的zip文件
	 * @return 返回文件字节数组
	 * @exception
	 */
	public static byte[] Decompress(MultipartFile file) throws IOException {
		GZIPInputStream gis = null;
		ByteArrayOutputStream baos = null;
		byte[] bt = null;
		try {
			gis = new GZIPInputStream(file.getInputStream());
			baos = new ByteArrayOutputStream();
			int count;
			byte data[] = new byte[BUFFER];
			while ((count = gis.read(data, 0, BUFFER)) != -1) {
				baos.write(data, 0, count);
			}

			bt = baos.toByteArray();

		} finally {
			if (baos != null) {
				baos.flush();
				baos.close();
			}
			if (gis != null) {
				gis.close();
			}

		}

		return bt;

		/*
		 * ZipInputStream zis = new ZipInputStream(file.getInputStream()); ZipEntry ze =
		 * null; while (((ze = zis.getNextEntry()) != null) && !ze.isDirectory()) {
		 * String name = ze.getName(); ByteArrayOutputStream baos = new
		 * ByteArrayOutputStream(); byte[] buffer = new byte[BUFFER]; int length = -1;
		 * while ((length = zis.read(buffer, 0, buffer.length)) > -1) {
		 * baos.write(buffer, 0, length); }
		 * 
		 * map.put(name, baos.toByteArray()); //baos.flush(); baos.close(); }
		 * 
		 * if (zis != null) { zis.close(); }
		 * 
		 * if (map.size() != 1) { throw new
		 * BusinessException(StatusCodeEnum.FILE_OPR_ERR,"zip文件包含多个json文件"); }
		 * 
		 * for (Map.Entry<String, byte[]> m : map.entrySet()) { result = m.getValue(); }
		 * 
		 * return result;
		 */
	}

	/**
	 * 文件解压缩
	 *
	 * @param path
	 * @param delete
	 *            是否删除原始文件
	 * @throws Exception
	 */
	public static void decompress(String path, boolean delete) throws Exception {
		File file = new File(path);
		decompress(file, delete);
	}

	public static Map<String, byte[]> unCompressFile() throws IOException {
		File file = new File("f:beijing.zip");
		InputStream in = new FileInputStream(file);
		ZipInputStream zis = new ZipInputStream(in);
		Map<String, byte[]> map = new HashMap<>();
		ZipEntry ze = null;
		int i = 0;
		while (((ze = zis.getNextEntry()) != null) && !ze.isDirectory()) {
			i++;
			String name = ze.getName();
			ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
			byte[] buffer = new byte[10240];
			int length = -1;
			while ((length = zis.read(buffer, 0, buffer.length)) > -1) {
				byteArrayOutputStream.write(buffer, 0, length);
			}

			map.put(name, byteArrayOutputStream.toByteArray());
			byteArrayOutputStream.close();
		}

		System.out.println("i:" + i);
		zis.close();
		return map;

	}

	public static byte[] getGzipByte(MultipartFile file) throws IOException {
		GZIPInputStream gis = null;
		ByteArrayOutputStream baos = null;
		byte[] bt = null;
		InputStream is = null;
		try {
			// gis = new GZIPInputStream(file.getInputStream());
			baos = new ByteArrayOutputStream();
			is = file.getInputStream();
			int count;
			byte data[] = new byte[BUFFER];
			while ((count = is.read(data, 0, BUFFER)) != -1) {
				baos.write(data, 0, count);
			}

			bt = baos.toByteArray();

		} finally {
			if (baos != null) {
				baos.flush();
				baos.close();
			}
			if (gis != null) {
				gis.close();
			}
			if (is != null) {
				is.close();
			}

		}

		return bt;
	}

	public static void main(String[] args) throws Exception {
		
		compress("C:\\Users\\her\\Desktop\\TRC_EXETCPU_REQ_11_20170524182356001"
				,false);

	}
}